package com.marketing.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.marketing.auth.dto.*;
import com.marketing.auth.entity.User;
import com.marketing.auth.mapper.UserMapper;
import com.marketing.auth.service.TokenService;
import com.marketing.auth.service.UserManagementService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户管理服务实现类
 */
@Service
public class UserManagementServiceImpl implements UserManagementService {

    private static final Logger logger = LoggerFactory.getLogger(UserManagementServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TokenService tokenService;

    // BCrypt密码加密器
    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    @Transactional
    public UserInfoDto createUser(CreateUserRequest request, String operator) {
        logger.info("开始创建用户，用户名: {}, 操作者: {}", request.getUsername(), operator);

        try {
            // 1. 验证用户名是否已存在
            if (isUsernameExist(request.getUsername())) {
                logger.warn("创建用户失败：用户名已存在，用户名: {}", request.getUsername());
                throw new RuntimeException("用户名已存在");
            }

            // 2. 验证邮箱是否已存在
            if (isEmailExist(request.getEmail())) {
                logger.warn("创建用户失败：邮箱已存在，邮箱: {}", request.getEmail());
                throw new RuntimeException("邮箱已存在");
            }

            // 3. 创建用户对象
            User user = new User();
            user.setUsername(request.getUsername());
            user.setEmail(request.getEmail());
            user.setPassword(passwordEncoder.encode(request.getPassword()));
            user.setNickname(StringUtils.hasText(request.getNickname()) ? request.getNickname() : request.getUsername());
            user.setPhone(request.getPhone());
            user.setRole(request.getRole());
            user.setDepartment(request.getDepartment());
            user.setPosition(request.getPosition());
            user.setStatus(1); // 默认启用
            user.setLoginCount(0);
            user.setCreateBy(operator);
            user.setUpdateBy(operator);
            user.setRemark(request.getRemark());
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());

            logger.debug("准备插入用户数据，用户名: {}", request.getUsername());

            // 4. 保存到数据库
            int insertResult = userMapper.insert(user);
            if (insertResult <= 0) {
                logger.error("创建用户失败：数据库插入失败，用户名: {}", request.getUsername());
                throw new RuntimeException("创建用户失败");
            }

            logger.info("用户创建成功，用户名: {}, 用户ID: {}, 操作者: {}", request.getUsername(), user.getId(), operator);

            // 5. 返回用户信息
            return convertToUserInfoDto(user);

        } catch (Exception e) {
            logger.error("创建用户过程中发生异常，用户名: {}, 操作者: {}, 异常: {}", request.getUsername(), operator, e.getMessage(), e);
            throw new RuntimeException("创建用户失败: " + e.getMessage(), e);
        }
    }

    @Override
    public UserInfoDto getUserById(Long userId) {
        logger.debug("根据ID查询用户，用户ID: {}", userId);

        try {
            User user = userMapper.selectById(userId);
            if (user == null) {
                logger.warn("用户不存在，用户ID: {}", userId);
                return null;
            }

            logger.debug("用户查询成功，用户ID: {}, 用户名: {}", userId, user.getUsername());
            return convertToUserInfoDto(user);

        } catch (Exception e) {
            logger.error("查询用户时发生异常，用户ID: {}, 异常: {}", userId, e.getMessage(), e);
            throw new RuntimeException("查询用户失败", e);
        }
    }

    @Override
    public UserInfoDto getUserByUsername(String username) {
        logger.debug("根据用户名查询用户，用户名: {}", username);

        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getUsername, username);
            User user = userMapper.selectOne(queryWrapper);

            if (user == null) {
                logger.debug("用户不存在，用户名: {}", username);
                return null;
            }

            logger.debug("用户查询成功，用户名: {}, 用户ID: {}", username, user.getId());
            return convertToUserInfoDto(user);

        } catch (Exception e) {
            logger.error("查询用户时发生异常，用户名: {}, 异常: {}", username, e.getMessage(), e);
            throw new RuntimeException("查询用户失败", e);
        }
    }

    @Override
    @Transactional
    public UserInfoDto updateUser(Long userId, UpdateUserRequest request, String operator) {
        logger.info("开始更新用户，用户ID: {}, 操作者: {}", userId, operator);

        try {
            // 1. 查询用户是否存在
            User existingUser = userMapper.selectById(userId);
            if (existingUser == null) {
                logger.warn("更新用户失败：用户不存在，用户ID: {}", userId);
                throw new RuntimeException("用户不存在");
            }

            // 2. 检查邮箱是否已被其他用户使用
            if (StringUtils.hasText(request.getEmail()) && !request.getEmail().equals(existingUser.getEmail())) {
                if (isEmailExist(request.getEmail(), userId)) {
                    logger.warn("更新用户失败：邮箱已被其他用户使用，邮箱: {}, 用户ID: {}", request.getEmail(), userId);
                    throw new RuntimeException("邮箱已被其他用户使用");
                }
            }

            // 3. 更新用户信息
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, userId);

            if (StringUtils.hasText(request.getEmail())) {
                updateWrapper.set(User::getEmail, request.getEmail());
            }
            if (StringUtils.hasText(request.getNickname())) {
                updateWrapper.set(User::getNickname, request.getNickname());
            }
            if (StringUtils.hasText(request.getPhone())) {
                updateWrapper.set(User::getPhone, request.getPhone());
            }
            if (request.getStatus() != null) {
                updateWrapper.set(User::getStatus, request.getStatus());
                // 如果禁用用户，清除其所有Token
                if (request.getStatus() == 0) {
                    logger.info("用户被禁用，清除所有Token，用户ID: {}", userId);
                    tokenService.removeUserAllTokens(userId);
                }
            }
            if (StringUtils.hasText(request.getRole())) {
                updateWrapper.set(User::getRole, request.getRole());
            }
            if (StringUtils.hasText(request.getDepartment())) {
                updateWrapper.set(User::getDepartment, request.getDepartment());
            }
            if (StringUtils.hasText(request.getPosition())) {
                updateWrapper.set(User::getPosition, request.getPosition());
            }
            if (StringUtils.hasText(request.getRemark())) {
                updateWrapper.set(User::getRemark, request.getRemark());
            }
            if (StringUtils.hasText(request.getAvatar())) {
                updateWrapper.set(User::getAvatar, request.getAvatar());
            }

            updateWrapper.set(User::getUpdateBy, operator);
            updateWrapper.set(User::getUpdateTime, LocalDateTime.now());

            int updateResult = userMapper.update(null, updateWrapper);
            if (updateResult <= 0) {
                logger.error("更新用户失败：数据库更新失败，用户ID: {}", userId);
                throw new RuntimeException("更新用户失败");
            }

            logger.info("用户更新成功，用户ID: {}, 操作者: {}", userId, operator);

            // 4. 返回更新后的用户信息
            return getUserById(userId);

        } catch (Exception e) {
            logger.error("更新用户过程中发生异常，用户ID: {}, 操作者: {}, 异常: {}", userId, operator, e.getMessage(), e);
            throw new RuntimeException("更新用户失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional
    public boolean deleteUser(Long userId, String operator) {
        logger.info("开始删除用户，用户ID: {}, 操作者: {}", userId, operator);

        try {
            // 1. 查询用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                logger.warn("删除用户失败：用户不存在，用户ID: {}", userId);
                return false;
            }

            // 2. 清除用户所有Token
            logger.debug("清除用户所有Token，用户ID: {}", userId);
            tokenService.removeUserAllTokens(userId);

            // 3. 删除用户
            int deleteResult = userMapper.deleteById(userId);
            if (deleteResult <= 0) {
                logger.error("删除用户失败：数据库删除失败，用户ID: {}", userId);
                return false;
            }

            logger.info("用户删除成功，用户ID: {}, 用户名: {}, 操作者: {}", userId, user.getUsername(), operator);
            return true;

        } catch (Exception e) {
            logger.error("删除用户过程中发生异常，用户ID: {}, 操作者: {}, 异常: {}", userId, operator, e.getMessage(), e);
            throw new RuntimeException("删除用户失败", e);
        }
    }

    @Override
    @Transactional
    public int batchDeleteUsers(List<Long> userIds, String operator) {
        logger.info("开始批量删除用户，用户ID列表: {}, 操作者: {}", userIds, operator);

        if (userIds == null || userIds.isEmpty()) {
            logger.warn("批量删除用户失败：用户ID列表为空");
            return 0;
        }

        int deletedCount = 0;
        try {
            for (Long userId : userIds) {
                try {
                    if (deleteUser(userId, operator)) {
                        deletedCount++;
                    }
                } catch (Exception e) {
                    logger.warn("删除用户失败，用户ID: {}, 异常: {}", userId, e.getMessage());
                }
            }

            logger.info("批量删除用户完成，总数: {}, 成功: {}, 操作者: {}", userIds.size(), deletedCount, operator);
            return deletedCount;

        } catch (Exception e) {
            logger.error("批量删除用户过程中发生异常，操作者: {}, 异常: {}", operator, e.getMessage(), e);
            throw new RuntimeException("批量删除用户失败", e);
        }
    }

    @Override
    @Transactional
    public boolean resetPassword(Long userId, ResetPasswordRequest request, String operator) {
        logger.info("开始重置用户密码，用户ID: {}, 操作者: {}", userId, operator);

        try {
            // 1. 查询用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                logger.warn("重置密码失败：用户不存在，用户ID: {}", userId);
                return false;
            }

            // 2. 更新密码
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, userId)
                    .set(User::getPassword, passwordEncoder.encode(request.getNewPassword()))
                    .set(User::getUpdateBy, operator)
                    .set(User::getUpdateTime, LocalDateTime.now());

            int updateResult = userMapper.update(null, updateWrapper);
            if (updateResult <= 0) {
                logger.error("重置密码失败：数据库更新失败，用户ID: {}", userId);
                return false;
            }

            // 3. 清除用户所有Token（强制重新登录）
            logger.debug("密码重置成功，清除用户所有Token，用户ID: {}", userId);
            tokenService.removeUserAllTokens(userId);

            logger.info("用户密码重置成功，用户ID: {}, 用户名: {}, 操作者: {}", userId, user.getUsername(), operator);
            return true;

        } catch (Exception e) {
            logger.error("重置密码过程中发生异常，用户ID: {}, 操作者: {}, 异常: {}", userId, operator, e.getMessage(), e);
            throw new RuntimeException("重置密码失败", e);
        }
    }

    @Override
    @Transactional
    public boolean updateUserStatus(Long userId, Integer status, String operator) {
        logger.info("开始更新用户状态，用户ID: {}, 状态: {}, 操作者: {}", userId, status, operator);

        try {
            // 1. 查询用户是否存在
            User user = userMapper.selectById(userId);
            if (user == null) {
                logger.warn("更新用户状态失败：用户不存在，用户ID: {}", userId);
                return false;
            }

            // 2. 更新状态
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getId, userId)
                    .set(User::getStatus, status)
                    .set(User::getUpdateBy, operator)
                    .set(User::getUpdateTime, LocalDateTime.now());

            int updateResult = userMapper.update(null, updateWrapper);
            if (updateResult <= 0) {
                logger.error("更新用户状态失败：数据库更新失败，用户ID: {}", userId);
                return false;
            }

            // 3. 如果禁用用户，清除其所有Token
            if (status == 0) {
                logger.info("用户被禁用，清除所有Token，用户ID: {}", userId);
                tokenService.removeUserAllTokens(userId);
            }

            logger.info("用户状态更新成功，用户ID: {}, 用户名: {}, 状态: {}, 操作者: {}", userId, user.getUsername(), status, operator);
            return true;

        } catch (Exception e) {
            logger.error("更新用户状态过程中发生异常，用户ID: {}, 操作者: {}, 异常: {}", userId, operator, e.getMessage(), e);
            throw new RuntimeException("更新用户状态失败", e);
        }
    }

    @Override
    public PageResult<UserInfoDto> getUserList(UserQueryRequest request) {
        logger.debug("开始分页查询用户列表，查询条件: {}", request);

        try {
            // 1. 构建查询条件
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();

            if (StringUtils.hasText(request.getUsername())) {
                queryWrapper.like(User::getUsername, request.getUsername());
            }
            if (StringUtils.hasText(request.getEmail())) {
                queryWrapper.like(User::getEmail, request.getEmail());
            }
            if (StringUtils.hasText(request.getNickname())) {
                queryWrapper.like(User::getNickname, request.getNickname());
            }
            if (StringUtils.hasText(request.getPhone())) {
                queryWrapper.like(User::getPhone, request.getPhone());
            }
            if (request.getStatus() != null) {
                queryWrapper.eq(User::getStatus, request.getStatus());
            }
            if (StringUtils.hasText(request.getRole())) {
                queryWrapper.eq(User::getRole, request.getRole());
            }
            if (StringUtils.hasText(request.getDepartment())) {
                queryWrapper.like(User::getDepartment, request.getDepartment());
            }
            if (StringUtils.hasText(request.getPosition())) {
                queryWrapper.like(User::getPosition, request.getPosition());
            }

            // 2. 排序
            switch (request.getSortBy()) {
                case "username":
                    if ("asc".equalsIgnoreCase(request.getSortOrder())) {
                        queryWrapper.orderByAsc(User::getUsername);
                    } else {
                        queryWrapper.orderByDesc(User::getUsername);
                    }
                    break;
                case "email":
                    if ("asc".equalsIgnoreCase(request.getSortOrder())) {
                        queryWrapper.orderByAsc(User::getEmail);
                    } else {
                        queryWrapper.orderByDesc(User::getEmail);
                    }
                    break;
                case "updateTime":
                    if ("asc".equalsIgnoreCase(request.getSortOrder())) {
                        queryWrapper.orderByAsc(User::getUpdateTime);
                    } else {
                        queryWrapper.orderByDesc(User::getUpdateTime);
                    }
                    break;
                case "lastLoginTime":
                    if ("asc".equalsIgnoreCase(request.getSortOrder())) {
                        queryWrapper.orderByAsc(User::getLastLoginTime);
                    } else {
                        queryWrapper.orderByDesc(User::getLastLoginTime);
                    }
                    break;
                case "loginCount":
                    if ("asc".equalsIgnoreCase(request.getSortOrder())) {
                        queryWrapper.orderByAsc(User::getLoginCount);
                    } else {
                        queryWrapper.orderByDesc(User::getLoginCount);
                    }
                    break;
                default: // createTime
                    if ("asc".equalsIgnoreCase(request.getSortOrder())) {
                        queryWrapper.orderByAsc(User::getCreateTime);
                    } else {
                        queryWrapper.orderByDesc(User::getCreateTime);
                    }
                    break;
            }

            // 3. 分页查询
            Page<User> page = new Page<>(request.getPageNum(), request.getPageSize());
            Page<User> resultPage = userMapper.selectPage(page, queryWrapper);

            // 4. 转换结果
            List<UserInfoDto> userInfoList = resultPage.getRecords().stream()
                    .map(this::convertToUserInfoDto)
                    .collect(Collectors.toList());

            PageResult<UserInfoDto> result = new PageResult<>(
                    userInfoList,
                    resultPage.getTotal(),
                    resultPage.getCurrent(),
                    resultPage.getSize()
            );

            logger.debug("用户列表查询成功，总数: {}, 当前页: {}, 每页大小: {}", result.getTotal(), result.getCurrent(), result.getSize());
            return result;

        } catch (Exception e) {
            logger.error("查询用户列表过程中发生异常，查询条件: {}, 异常: {}", request, e.getMessage(), e);
            throw new RuntimeException("查询用户列表失败", e);
        }
    }

    @Override
    public boolean isUsernameExist(String username) {
        logger.debug("检查用户名是否存在，用户名: {}", username);

        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getUsername, username);
            Long count = userMapper.selectCount(queryWrapper);
            
            boolean exists = count > 0;
            logger.debug("用户名存在性检查结果，用户名: {}, 存在: {}", username, exists);
            return exists;

        } catch (Exception e) {
            logger.error("检查用户名是否存在时发生异常，用户名: {}, 异常: {}", username, e.getMessage(), e);
            throw new RuntimeException("检查用户名失败", e);
        }
    }

    @Override
    public boolean isEmailExist(String email) {
        logger.debug("检查邮箱是否存在，邮箱: {}", email);

        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getEmail, email);
            Long count = userMapper.selectCount(queryWrapper);
            
            boolean exists = count > 0;
            logger.debug("邮箱存在性检查结果，邮箱: {}, 存在: {}", email, exists);
            return exists;

        } catch (Exception e) {
            logger.error("检查邮箱是否存在时发生异常，邮箱: {}, 异常: {}", email, e.getMessage(), e);
            throw new RuntimeException("检查邮箱失败", e);
        }
    }

    @Override
    public boolean isUsernameExist(String username, Long excludeUserId) {
        logger.debug("检查用户名是否存在（排除指定用户），用户名: {}, 排除用户ID: {}", username, excludeUserId);

        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getUsername, username)
                    .ne(User::getId, excludeUserId);
            Long count = userMapper.selectCount(queryWrapper);
            
            boolean exists = count > 0;
            logger.debug("用户名存在性检查结果（排除指定用户），用户名: {}, 存在: {}", username, exists);
            return exists;

        } catch (Exception e) {
            logger.error("检查用户名是否存在时发生异常，用户名: {}, 排除用户ID: {}, 异常: {}", username, excludeUserId, e.getMessage(), e);
            throw new RuntimeException("检查用户名失败", e);
        }
    }

    @Override
    public boolean isEmailExist(String email, Long excludeUserId) {
        logger.debug("检查邮箱是否存在（排除指定用户），邮箱: {}, 排除用户ID: {}", email, excludeUserId);

        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getEmail, email)
                    .ne(User::getId, excludeUserId);
            Long count = userMapper.selectCount(queryWrapper);
            
            boolean exists = count > 0;
            logger.debug("邮箱存在性检查结果（排除指定用户），邮箱: {}, 存在: {}", email, exists);
            return exists;

        } catch (Exception e) {
            logger.error("检查邮箱是否存在时发生异常，邮箱: {}, 排除用户ID: {}, 异常: {}", email, excludeUserId, e.getMessage(), e);
            throw new RuntimeException("检查邮箱失败", e);
        }
    }

    /**
     * 将User对象转换为UserInfoDto
     */
    private UserInfoDto convertToUserInfoDto(User user) {
        logger.debug("开始转换User对象为UserInfoDto，用户ID: {}", user.getId());
        
        try {
            UserInfoDto dto = new UserInfoDto();
            dto.setId(user.getId());
            dto.setUsername(user.getUsername());
            dto.setEmail(user.getEmail());
            dto.setNickname(user.getNickname());
            dto.setAvatar(user.getAvatar());
            dto.setPhone(user.getPhone());
            dto.setStatus(user.getStatus());
            dto.setRole(user.getRole());
            dto.setDepartment(user.getDepartment());
            dto.setPosition(user.getPosition());
            dto.setLoginCount(user.getLoginCount());
            
            logger.debug("User对象转换成功，用户ID: {}, 用户名: {}", user.getId(), user.getUsername());
            return dto;
        } catch (Exception e) {
            logger.error("User对象转换失败，用户ID: {}, 异常: {}", user.getId(), e.getMessage(), e);
            throw new RuntimeException("User对象转换失败", e);
        }
    }
}